package game.combat;

import character.CharacterCombatControl;
import character.MyCharacter;
import character.ai.AIGeneralControl;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import game.DataStore;
import game.GameUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import player.AIPlayer;

public class CombatAppState extends AbstractAppState {
    protected TurnAppState turnAppState;
    protected ResolutionAppState resolutionAppState;
    protected boolean readyForTurn = true;
    protected boolean readyForResolution = false;

    public CombatAppState() {
	turnAppState = new TurnAppState(this);
	resolutionAppState = new ResolutionAppState(this);
    }

    @Override
    public void stateAttached(AppStateManager stateManager) {
	super.stateAttached(stateManager);
	turnAppState.setEnabled(false);
	stateManager.attach(turnAppState);
	resolutionAppState.setEnabled(false);
	stateManager.attach(resolutionAppState);
    }

    @Override
    public void setEnabled(boolean enabled) {
	super.setEnabled(enabled);
	if(enabled) {
	    for(MyCharacter character : GameUtil.getAllCharactersInWorld()) {
		character.addControl(new CharacterCombatControl(new CapsuleCollisionShape(MyCharacter.RADIUS, MyCharacter.HEIGHT)));
		if(character.getPlayer() instanceof AIPlayer) {
                    character.addControl(character.getControl(AIGeneralControl.class).getAILogicCombatControl());
                }
                DataStore.bulletAppState.getPhysicsSpace().addAll(character);
	    }
	} else {
	    turnAppState.setEnabled(false);
	    resolutionAppState.setEnabled(false);
	    for(MyCharacter character : GameUtil.getAllCharactersInWorld()) {
		DataStore.bulletAppState.getPhysicsSpace().removeAll(character);
		character.removeControl(CharacterCombatControl.class);
                if(character.getPlayer() instanceof AIPlayer) {
                    character.removeControl(character.getControl(AIGeneralControl.class).getAILogicCombatControl());
                }
	    }
	}
    }

    @Override
    public void update(float tpf) {
	super.update(tpf);
	if(readyForTurn) {
            readyForTurn = false;
            turnAppState.setEnabled(true);
	} else if(readyForResolution) {
	    readyForResolution = false;
	    resolutionAppState.setEnabled(true);
	}
    }

    public void endCharacterTurnSegment() {
	turnAppState.setEnabled(false);
	resolutionAppState.setCharacterListener(((MyCharacter)getCurrentCombatActor()).getControl(CharacterCombatControl.class));
        readyForResolution = true;
    }

    public void resolutionEnded() {
	resolutionAppState.setEnabled(false);
	readyForTurn = true;
    }

    public void turnEnded() {
	turnAppState.setEnabled(false);
	readyForTurn = true;
    }

    /* Below are shortcut methods so that all communication with Turn and Resolution app states happens through here. */

    public Collection<CombatActor> getCombatActors() {
        return turnAppState.getCombatActors();
    }
    public Collection<MyCharacter> getCombatActorCharacters() {
        List<MyCharacter> characters = new ArrayList<MyCharacter>();
        for(CombatActor combatActor : turnAppState.getCombatActors()) {
            if(combatActor instanceof MyCharacter)
                characters.add((MyCharacter)combatActor);
        }
        return characters;
    }
    public void setCombatActors(Collection<CombatActor> combatActors) {
        turnAppState.setCombatActors(combatActors);
    }
    public void addCombatActorAtCurrentInitiative(CombatActor combatActor) {
        combatActor.setInitiative(turnAppState.getCurrentCombatActor().getInitiative());
        turnAppState.addCombatActor(combatActor);
    }
    public void removeCombatActor(CombatActor combatActor) {
        turnAppState.removeCombatActor(combatActor);
    }
    public CombatActor getCurrentCombatActor() {
	return turnAppState.getCurrentCombatActor();
    }
    public void endCharacterTurn() {
        turnAppState.endTurn();
    }
    
    public void registerConstantResolutionListener(ResolutionListener listener) {
        resolutionAppState.registerConstantListener(listener);
    }
    public void registerTemporaryResolutionListener(ResolutionListener listener) {
        resolutionAppState.registerTemporaryListener(listener);
    }
    public void removeTemporaryResolutionListener(ResolutionListener listener) {
        resolutionAppState.removeTemporaryListener(listener);
    }
}
